/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.lvyh.lightframe.core.config;

import com.lvyh.lightframe.core.consumer.proxy.ProxyManager;
import com.lvyh.lightframe.core.generic.GenericService;
import com.lvyh.lightframe.common.util.ClassUtils;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.io.Serializable;

/**
 * @author lvyh 2021/05/16.
 */
@Data
@Slf4j
public class ReferenceConfig<T> implements Serializable {

    /**
     * generic invoke
     */
    private boolean generic;

    /**
     * Service interface: as part of the unique identity of a service
     */
    protected String interfaceId;

    /**
     * Service tag: as part of the unique identification of a service
     */
    protected String uniqueId;

    /**
     * proxy type
     */
    protected String proxy;

    /**
     * Proxy interface class, corresponding to t, is mainly for generic calls
     */
    protected transient volatile Class proxyClass;

    /**
     * Service consumer configuration
     */
    protected ConsumerConfig consumerConfig;

    /**
     * @param consumerConfig Service consumer configuration
     */
    protected ReferenceConfig(ConsumerConfig consumerConfig) {
        this.consumerConfig = consumerConfig;
    }

    /**
     * @return Service consumer configuration
     */
    public ConsumerConfig getConsumerConfig() {
        return consumerConfig;
    }

    public ReferenceConfig() {

    }

    public ReferenceConfig setUniqueId(String uniqueId) {
        this.uniqueId = uniqueId;
        return this;
    }

    public ReferenceConfig setInterfaceId(String interfaceId) {
        this.interfaceId = interfaceId;
        return this;
    }

    public ReferenceConfig setProxy(String proxy) {
        this.proxy = proxy;
        return this;
    }


    public ReferenceConfig setGeneric(boolean generic) {
        this.generic = generic;
        return this;
    }

    public Class<?> getProxyClass() {
        if (proxyClass != null) {
            return proxyClass;
        }
        if (generic) {
            return GenericService.class;
        }
        try {
            if (StringUtils.isNotBlank(interfaceId)) {
                this.proxyClass = ClassUtils.forName(interfaceId);
                if (!proxyClass.isInterface()) {
                    throw new RuntimeException("interface:" + interfaceId + " must be interface class, not implement class");
                }
            } else {
                throw new RuntimeException("interface" + interfaceId + "interfaceId must be not null");
            }
        } catch (RuntimeException t) {
            throw new IllegalStateException(t.getMessage(), t);
        }
        return proxyClass;
    }

    /**
     * Gets proxy.
     */
    public String getProxy() {
        return proxy;
    }

    public T refer() {
        //Create client proxy object
        ProxyManager proxyManager = ProxyManager.getInstance();
        Object serviceProxy = proxyManager.getProxy(getProxyClass(), this);
        return (T) serviceProxy;
    }


}
